using System;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Text;
using WatiN.Core.DialogHandlers;
using Wax.Properties;

namespace Wax
{
    /// <summary>
    /// Used to attach and interact with dialogs
    /// </summary>
    public class DialogHandlerCommand : Command
    {
        #region Private fields

        /// <summary>
        /// Gets the type of the dialog.
        /// </summary>
        private DialogHandlerType dialogType = DialogHandlerType.None;

        private string dialogId;

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="DialogHandlerCommand"/> class.
        /// </summary>
        public DialogHandlerCommand()
        {
        }

        #endregion

        #region Public instance properties

        /// <summary>
        /// Gets the type of the dialog.
        /// </summary>
        /// <value>The type of the dialog.</value>
        public DialogHandlerType DialogType
        {
            get { return dialogType; }
        }

        /// <summary>
        /// Gets the dialog id.
        /// </summary>
        /// <value>The dialog id.</value>
        public string DialogId
        {
            get { return dialogId; }
        }

        #endregion

        #region Public instance methods

        /// <summary>
        /// Executes this command
        /// </summary>
        /// <param name="context">The execution context used to execute this command</param>
        [CLSCompliant(false)]
        public override void Execute(IExecutionContext context)
        {
            switch (this.CommandType)
            {
                case CommandType.AttachDialogHandler:
                    this.ExecuteAttachDialogHandler(context);
                    break;
                case CommandType.GetJavaDialogMessage:
                    this.ExecuteGetJavaDialogMessage(context);
                    break;
                default:
                    base.Execute(context);
                    break;
            }
        }

        #endregion
    
        #region Internal instance methods

        internal override void Initialize()
        {
            base.Initialize();
            this.ParseDialogType();
            this.dialogId = this.Arguments[1];
        }

        #endregion

        #region Private methods

        private void ExecuteAttachDialogHandler(IExecutionContext context)
        {
            switch(this.DialogType)
            {
                case DialogHandlerType.SimpleJavaDialog:
                    context.AddDialogHandler(this.dialogId, new WatiN.Core.DialogHandlers.SimpleJavaDialogHandler());
                    break;
                case DialogHandlerType.ConfirmDialog:
                    context.AddDialogHandler(this.dialogId, new WatiN.Core.DialogHandlers.ConfirmDialogHandler());
                    break;
                default:
                    throw new ExecutionException(string.Format(CultureInfo.InvariantCulture, Resource.ExecuteAttachDialogHandlerInvalidValue, this.DialogType));
            }
        }

        /// <summary>
        /// Executes the java dialog get message.
        /// </summary>
        /// <param name="context">The context.</param>
        private void ExecuteGetJavaDialogMessage(IExecutionContext context)
        {
            switch (this.DialogType)
            {
                case DialogHandlerType.SimpleJavaDialog:
                    SimpleJavaDialogHandler handler = context.GetDialogHandler(this.DialogId) as WatiN.Core.DialogHandlers.SimpleJavaDialogHandler;

                    if (handler != null)
                    {
                        context.LastFoundValue = handler.Message;
                    }
                    else
                    {
                        throw new ExecutionException(string.Format(CultureInfo.InvariantCulture, Resource.ExecuteGetJavaDialogMessageNoIdAdded, this.DialogId));
                    }
                    break;
                default:
                    throw new ExecutionException(string.Format(CultureInfo.InvariantCulture, Resource.ExecuteAttachDialogHandlerInvalidValue, this.DialogType));
            }
        }

        private void ParseDialogType()
        {
            string argument = this.Arguments[0];
            if (string.IsNullOrEmpty(argument))
            {
                throw new ParseException("An argument must be supplied specifying the type of dialog");
            }

            if (argument.Equals("simplejavadialog", StringComparison.CurrentCultureIgnoreCase))
            {
                this.dialogType = DialogHandlerType.SimpleJavaDialog;
            }
            else if (argument.Equals("confirmdialog", StringComparison.CurrentCultureIgnoreCase))
            {
                this.dialogType = DialogHandlerType.ConfirmDialog;
            }
            else
            {
                throw new ArgumentOutOfRangeException(
                    string.Format(CultureInfo.InvariantCulture, "Can not parse unknown dialog handler type: {0}.", argument));
            }
        }

        #endregion
    }
}
